package com.kylin.shared.common;

import com.kylin.shared.enums.ResultCodeEnum;
import com.kylin.shared.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.eventhandling.gateway.EventGateway;
import org.axonframework.messaging.responsetypes.ResponseTypes;
import org.axonframework.queryhandling.QueryGateway;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * 查询功能
 * @author Damon S.
 * @version v1.0.1
 * @date 2020年05月31日 13:27
 */
@Slf4j
@RequiredArgsConstructor
public class FunctionProvider {

    private final QueryGateway queryGateway;
    private final CommandGateway commandGateway;
    private final EventGateway eventGateway;


    /**命令发送*/
    protected  <R> R sendCommand(Object command) {
        return this.commandGateway.sendAndWait(
                Optional.ofNullable(command)
                        .orElseThrow(() -> new BusinessException(ResultCodeEnum.DATA_ERROR, "发送的命令对象不能为空"))
        );
    }

    /**事件分发*/
    protected void dispatchEvent(KylinEvent event) {
        this.eventGateway.publish(
                Optional.ofNullable(event)
                        .orElseThrow(() -> new BusinessException(ResultCodeEnum.DATA_ERROR, "发布的事件对象不能为空"))
        );
    }

    protected  <T> T executeQuery(Object command, Class<T> clazz) {
        T queryResult;
        try {
            CompletableFuture<T> futureResults = queryGateway.query(
                    command,
                    ResponseTypes.instanceOf(clazz)
            );
            queryResult = futureResults.get();
        } catch (Exception e) {
            log.error("查询数据[Class={}]失败。ERROR:{}", clazz, e.getMessage());
            throw new BusinessException(ResultCodeEnum.DATA_ERROR, e.getMessage());
        }
        return queryResult;
    }
}
